package com.dianxin.secure.persist;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.msgpack.MessagePack;

import redis.clients.jedis.Jedis;

import com.dianxin.secure.model.Secure;

public  class RedisDao<T extends Secure> implements
		RedisDaoInterface<T> {
	private Log log = LogFactory.getLog(getClass());
	private static MessagePack converter = new MessagePack();
	private static RedisStore redisStore = new RedisStore();
	public static Jedis jedis = redisStore.borrowJedis();
    private   Secure secure;

	
	
	public int getNumber() {
		int result = 0;
		Long num = jedis.zcard(getTotalKey());
		result = num.intValue();
		return result;
	}
	
	public int getNumberByName(String name) {
		int result = 0;
		Long num = jedis.zcard(getSecureKey(name));
		result = num.intValue();
		return result;
	}

	
	
	public Set<String> get(int pageNumber, int pageSize)  {
		int start = (pageNumber - 1) * pageSize;
		int end = start + pageSize - 1;
		Set<String> names = jedis.zrange(getTotalKey(), start, end);
		return names;
	}

	
	
	public Set<T> getByPath(final String path) {
		Set<T> result = new HashSet<T>();
		String key = getFileKey(path);
		Set<?> bytes = jedis.zrange(key.getBytes(), 0, -1);
		for (Object object : bytes) {
			try {
				T oneSecure = (T) converter.read((byte[]) object, new Secure());
				result.add(oneSecure);
			} catch (Exception e) {
				log.error(e);
			}
		}
		return result;
	}

	
	
	public Set<T> getByName(final String name)  {
		Set<T> result = new HashSet<T>();
		String key = getSecureKey(name);
		Set<?> bytes = jedis.zrange(key.getBytes(), 0, -1);
		for (Object object : bytes) {
			try {
				T oneSecure = (T) converter.read((byte[]) object,  new Secure());
				result.add(oneSecure);
			} catch (Exception e) {
				log.error(e);
			}
		}
		return result;
	}
	
	public Set<T> getPage(final String name,int pageNumber, int pageSize)  {
		int start = (pageNumber - 1) * pageSize;
		int end = start + pageSize - 1;
		Set<T> result = new HashSet<T>();
		String key = getSecureKey(name);
		Set<?> bytes = jedis.zrange(key.getBytes(), start, end);
		for (Object object : bytes) {
			try {
				T oneSecure = (T) converter.read((byte[]) object, new Secure());
				result.add(oneSecure);
			} catch (Exception e) {
				log.error(e);
			}
		}
		return result;
	}

	
	
	public T getByNameAndPath(final String name, final String path)
			throws IOException, InstantiationException, IllegalAccessException {
		T result = null;
		String key = getSecureKey(name);
		Set<?> bytes = jedis.zrange(key.getBytes(), 0, -1);
		for (Object object : bytes) {
			T oneSecure = (T) converter.read((byte[]) object, new Secure());
			if (oneSecure.getPath().equals(path)) {
				result = oneSecure;
				break;
			}
		}
		return result;
	}

	
	
	public void save(final T secure) throws IOException {
		saveSecureKey(secure);
		saveFileKey(secure);
		saveTotal(secure);
	}

	
	
	public void saveSecureKey(final T secure) throws IOException {
		String key = getSecureKey(secure.getName());
		saveFileKey(key, secure);
	}

	
	
	public void saveFileKey(final T secure) throws IOException {
		String fileKey = getFileKey(secure.getPath());
		saveFileKey(fileKey, secure);
	}

	private void saveTotal(T secure) {
		String key = getTotalKey();
		saveFileKey(key, secure.getName());
	}

	
	
	public void saveFileKey(final String key, final String value) {
		jedis.zadd(key, 1, value);

	}

	
	
	public void saveFileKey(final String key, final Secure secure)
			throws IOException {
		byte[] secureByte = converter.write(secure);
		jedis.zadd(key.getBytes(), 1, secureByte);

	}

	
	
	public void update(final T oldSecure, final T newSecure)
			throws IOException, InstantiationException, IllegalAccessException {
		delete(oldSecure);
		save(newSecure);
	}

	
	
	public T delete(T secure) throws IOException, InstantiationException,IllegalAccessException {
		deleteSecureKey(secure);
		deleteFileKey(secure);
		deleteTotal(secure);
		return null;

	}

	private void deleteTotal(T secure) throws IOException,
			InstantiationException, IllegalAccessException {
		String key = getTotalKey();
		Set<T> set = getByName(secure.getName());
		if (set.isEmpty()) {
			deleteKey(key, secure.getName());
		}
	}

	
	
	public void deleteSecureKey(T secure) throws IOException {
		String key = getSecureKey(secure.getName());
		deleteKey(key, secure);
	}

	
	
	public void deleteFileKey(T secure) throws IOException {
		String key = getFileKey(secure.getPath());
		deleteKey(key, secure);
	}

	
	
	public void deleteKey(final String key, final String value) {
		jedis.zrem(key, value);
	}

	
	
	public void deleteKey(final String key, final Secure secure)
			throws IOException {
		Set<byte[]> set = jedis.zrange(key.getBytes(), 0, -1);
		for (byte[] one : set) {
            Secure oneSecure = converter.read(one, Secure.class);
			if (oneSecure.equals(secure)) {
				jedis.zrem(key.getBytes(), one);
				break;
			}
		}

	}

	
	

	
	

	
	
	public  String getSecureKey(final String name){
        return  secure.getType()+name;
    }

	
	
	public  String getFileKey(final String name){
        return  secure.getFileKey()+name;
    }

	
	
	public  String getTotalKey(){
        return  secure.getTotalKey();
    }


    public void setSecure(Secure secure) {
        this.secure = secure;
    }
}
